package com.qaml.mes.device.application.task;

import com.alibaba.nacos.common.utils.CollectionUtils;
import com.qaml.mes.device.dao.*;
import com.qaml.mes.device.repository.*;
import com.qaml.mes.device.utils.DateUtils;
import com.qaml.mes.device.utils.IdGenerateUtils;
import com.qaml.mes.device.enums.CheckUpkeepMessageTypeEnum;
import com.qaml.mes.device.enums.CheckUpkeepStatusEnum;
import com.qaml.mes.device.enums.CheckUpkeepTypeEnum;
import com.qaml.mes.device.enums.CheckUpkeepUserTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.util.*;

/**
 * @ClassName CreateUpkeepOrderTask
 * @Description 创建保养任务单
 * @Author leikai
 * @Date 2024/3/5 0005 17:09
 * @Version 1.0
 */
@Slf4j
@Component
@RefreshScope
public class CreateUpkeepOrderTask {

    @Resource
    private CheckUpkeepInfoRepository checkUpkeepInfoRepository;

    @Resource
    private CheckUpkeepItemRepository checkUpkeepItemRepository;

    @Resource
    private CheckUpkeepUserRepository checkUpkeepUserRepository;

    @Resource
    private CheckUpkeepRecordRepository checkUpkeepRecordRepository;

    @Resource
    private CheckUpkeepRecordItemRepository checkUpkeepRecordItemRepository;

    @Resource
    private CheckUpkeepMessageRepository checkUpkeepMessageRepository;

    @Resource
    private TransactionTemplate transactionTemplate;

    @Resource
    private DayOffRepository dayOffRepository;


    /**
     * 每周日0点30分执行
     */
    @Scheduled(cron = "${upkeep.order.task:0 0/2 * * * ?}")
    public void createUpkeepOrder() {
        log.info("创建保养任务单开始~");
        List<CheckUpkeepInfoDO> checkUpkeepInfoDOList = checkUpkeepInfoRepository.getCheckUpkeepInfoDOByType(CheckUpkeepTypeEnum.UPKEEP.getType());
        if (CollectionUtils.isNotEmpty(checkUpkeepInfoDOList)) {
            Map<Long, List<DayOffConfigDO>> objectObjectHashMap = new HashMap<>();
            checkUpkeepInfoDOList.forEach(checkUpkeepInfoDO -> {
                List<DayOffConfigDO> dayOffConfigDOS = checkDayOffData(objectObjectHashMap, checkUpkeepInfoDO, dayOffRepository);
                if (CollectionUtils.isEmpty(dayOffConfigDOS)) {
                    try {
                        transactionTemplate.executeWithoutResult(status -> {
                            try {
                                // 保存检保记录
                                String checkUpkeepRecordId = saveCheckUpkeepInfo(checkUpkeepInfoDO);
                                // 保存检保项目条目记录
                                saveRecordItem(checkUpkeepInfoDO, checkUpkeepRecordId);
                                // 发送保养消息
                                saveMessage(checkUpkeepInfoDO, checkUpkeepRecordId);
                            } catch (DuplicateKeyException e) {
                                log.warn("重复创建保养任务单~, 检保项目编号:{}", checkUpkeepInfoDO.getCheckUpkeepId());
                            }
                        });
                    } catch (Exception e) {
                        log.error("检保项目生成保养任务单异常 {}", checkUpkeepInfoDO.getCheckUpkeepId(), e);
                    }
                } else {
                    log.info("当前租户 {} 因当前时间配置了假期管理数据,所以无需生成保养单", checkUpkeepInfoDO.getTenantId());
                }

            });
        }
        log.info("创建保养任务单结束~");

    }

    public static List<DayOffConfigDO> checkDayOffData(Map<Long, List<DayOffConfigDO>> objectObjectHashMap, CheckUpkeepInfoDO checkUpkeepInfoDO, DayOffRepository dayOffRepository) {
        List<DayOffConfigDO> dayOffConfigDOS = objectObjectHashMap.get(checkUpkeepInfoDO.getTenantId());
        if (dayOffConfigDOS == null) {
            dayOffConfigDOS = dayOffRepository.getDoByTenantAndDate(checkUpkeepInfoDO.getTenantId(), new Date());
            if (dayOffConfigDOS == null) {
                dayOffConfigDOS = new ArrayList<>();
            }
            objectObjectHashMap.put(checkUpkeepInfoDO.getTenantId(), dayOffConfigDOS);
        }
        return dayOffConfigDOS;
    }

    private void saveMessage(CheckUpkeepInfoDO checkUpkeepInfoDO, String checkUpkeepRecordId) {
        List<CheckUpkeepUserDO> checkUpkeepUserDOS = checkUpkeepUserRepository.getByCheckUpkeepIdAndStatusNoTenantId(checkUpkeepInfoDO.getCheckUpkeepId(),
                CheckUpkeepUserTypeEnum.CHECK.getType());
        if (CollectionUtils.isNotEmpty(checkUpkeepUserDOS)) {
            List<CheckUpkeepMessageDO> checkUpkeepMessages = new ArrayList<>();
            checkUpkeepUserDOS.forEach(checkUpkeepUserDO -> {
                CheckUpkeepMessageDO checkUpkeepMessageDO = new CheckUpkeepMessageDO();
                checkUpkeepMessageDO.setId(IdGenerateUtils.getIdStr());
                checkUpkeepMessageDO.setCheckUpkeepId(checkUpkeepInfoDO.getCheckUpkeepId());
                checkUpkeepMessageDO.setCheckUpkeepRecordId(checkUpkeepRecordId);
                checkUpkeepMessageDO.setType(CheckUpkeepMessageTypeEnum.UPKEEP.getType());
                checkUpkeepMessageDO.setUserId(checkUpkeepUserDO.getUserId());
                checkUpkeepMessageDO.setUserName(checkUpkeepUserDO.getUserName());
                checkUpkeepMessageDO.setSendTime(new Date());
                checkUpkeepMessageDO.setStatus(CheckUpkeepStatusEnum.NO_COMMIT.getType());
                checkUpkeepMessageDO.setCheckUpkeepDate(DateUtils.getStartDate(new Date()));
                checkUpkeepMessageDO.setIsRead(0);
                checkUpkeepMessageDO.setEqpName(checkUpkeepInfoDO.getEqpName());
                checkUpkeepMessages.add(checkUpkeepMessageDO);
            });
            checkUpkeepMessageRepository.saveBatch(checkUpkeepMessages);
        }
    }

    private void saveRecordItem(CheckUpkeepInfoDO checkUpkeepInfoDO, String checkUpkeepRecordId) {
        List<CheckUpkeepItemDO> checkUpkeepItemDOS = checkUpkeepItemRepository.getByCheckUpkeepId(checkUpkeepInfoDO.getCheckUpkeepId());
        if (CollectionUtils.isNotEmpty(checkUpkeepItemDOS)) {
            List<CheckUpkeepRecordItemDO> checkUpkeepRecordsList = new ArrayList<>();
            checkUpkeepItemDOS.forEach(checkUpkeepItemDO -> {
                CheckUpkeepRecordItemDO checkUpkeepRecordItemDO = new CheckUpkeepRecordItemDO();
                checkUpkeepRecordItemDO.setCheckUpkeepRecordId(checkUpkeepRecordId);
                checkUpkeepRecordItemDO.setCheckItem(checkUpkeepItemDO.getCheckItem());
                checkUpkeepRecordItemDO.setCheckUpkeepItemId(checkUpkeepItemDO.getId());
                checkUpkeepRecordItemDO.setId(IdGenerateUtils.getIdStr());
                checkUpkeepRecordItemDO.setTenantId(checkUpkeepInfoDO.getTenantId());
                checkUpkeepRecordItemDO.setStatus(1);
                checkUpkeepRecordsList.add(checkUpkeepRecordItemDO);
            });
            checkUpkeepRecordItemRepository.saveBatch(checkUpkeepRecordsList);
        }
    }

    private String saveCheckUpkeepInfo(CheckUpkeepInfoDO checkUpkeepInfoDO) {
        CheckUpkeepRecordDO checkUpkeepRecordDO = new CheckUpkeepRecordDO();
        checkUpkeepRecordDO.setCheckUpkeepId(checkUpkeepInfoDO.getCheckUpkeepId());
        checkUpkeepRecordDO.setEqpId(checkUpkeepInfoDO.getEqpId());
        checkUpkeepRecordDO.setEqpCode(checkUpkeepInfoDO.getEqpCode());
        checkUpkeepRecordDO.setEqpName(checkUpkeepInfoDO.getEqpName());
        checkUpkeepRecordDO.setType(checkUpkeepInfoDO.getType());
        checkUpkeepRecordDO.setCycle(checkUpkeepInfoDO.getCycle());
        checkUpkeepRecordDO.setLineBody(checkUpkeepInfoDO.getLineBody());
        checkUpkeepRecordDO.setTenantId(checkUpkeepInfoDO.getTenantId());
        // 检保时间
        Date now = new Date();
        // 如果是按周查询，则需要构造一周的开始和结束时间
        Date startDateOfWeek = DateUtils.getStartDate(DateUtils.getStartDateByWeek(now));
        Date endDateOfWeek = DateUtils.getEndDate(DateUtils.getEndDateByWeek(now));
        checkUpkeepRecordDO.setCheckUpkeepDate(DateUtils.getStartDate(now));
        checkUpkeepRecordDO.setCheckUpkeepStartTime(startDateOfWeek);
        checkUpkeepRecordDO.setCheckUpkeepEndTime(endDateOfWeek);
        checkUpkeepRecordDO.setStatus(CheckUpkeepStatusEnum.NO_COMMIT.getType());
        checkUpkeepRecordDO.setErrResult(0);
        checkUpkeepRecordRepository.saveCheckUpkeepRecordDO(checkUpkeepRecordDO);
        return checkUpkeepRecordDO.getId();
    }


}